package com.om.base;

import com.om.common.ConfigReader;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import com.sun.xml.internal.bind.v2.runtime.reflect.opt.Const;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Sql查询的过滤条件集合类
 * @author Administrator
 *
 */
public class SqlFilter implements Serializable {
	public static final String IS_NULL =" is null ";
	public static final String IS_NOT_NULL =" is not null ";
	
	public HashMap filterMap = new HashMap();
	public HashMap<String, String> opMap = new HashMap();
	public HashMap<SqlFilter,String> childMap = new HashMap<SqlFilter,String>();
    public  ArrayList<String> Fields = new ArrayList<String>();
    private HashMap<OP, String> enumMap = new HashMap();
    private String rel = " AND ";
    private String fields = "";
    private String values = "";
    public  String attachCondition = "";
    public  ArrayList<String> ExtendFields = new ArrayList<String>();
    public boolean translate2Lucene = false;
    /**
     * 基本构造函数（构造函数中初始化操作符的枚举）
     */
    public SqlFilter() {
        initEnumMap();
    }
    
    public static SqlFilter SplitStr2Filters(String field,String value,String spliter,boolean isOr){
    	SqlFilter filter = new SqlFilter();
    	String[] arr = value.split(spliter);
    	if(arr!=null){
    		for(int i=0;i<arr.length;i++){
    			if(i==0){
    				filter.addFilter(field, SqlFilter.OP.EQUALS,arr[i]);
    			}
    			else{
    				filter.addFilter(new SqlFilter(field, SqlFilter.OP.EQUALS,arr[i]),isOr);
    			}
    		}
    	}
    	return filter;
    }

    /**
     * 带条件的构造函数
     * 1、构造函数中初始化操作符的枚举
     * 2、把需要添加的条件以构造函数参数的形式添加到集合
     * @param field 需要添加的字段
     * @param operate 操作符
     * @param value 字段
     * @return 当前对象的引用
     *
     */
    public SqlFilter(String field, OP operate, Object value) {
        initEnumMap();
        addFilter(field, operate, value);
    }

    public SqlFilter(boolean isOr) {
        this.rel = ((isOr) ? " OR " : " AND ");
        initEnumMap();
    }

    /**
     * 获取过滤条件的个数
     */
    public int getFilterItemCount() {
        return this.filterMap.keySet().size();
    }

    private void initEnumMap() {
        this.enumMap.put(OP.EQUALS, " = ");
        this.enumMap.put(OP.NOT_EQUALS, " <> ");
        this.enumMap.put(OP.LIKE, " like ");
        this.enumMap.put(OP.NOT_LIKE, " not like  ");
        this.enumMap.put(OP.MORETHEN, " > ");
        this.enumMap.put(OP.MORETHEN_OR_EQUALS, " >= ");
        this.enumMap.put(OP.LESSTHEN, " < ");
        this.enumMap.put(OP.LESSTHEN_OR_EQUALS, " <= ");
        this.enumMap.put(OP.LEFT_LIKE, " llike ");
        this.enumMap.put(OP.RIGHT_LIKE, " rlike ");
        this.enumMap.put(OP.IN, " in ");
        this.enumMap.put(OP.NOT_IN, " not in ");
        
    }

    /**
     * 把过滤条件转成xml字符串用于传输
     */
    public String getXml() {
        String strXml = "";

        try {
            Iterator keys = this.filterMap.keySet().iterator();

            while (keys.hasNext()) {
                String key = (String) keys.next();
                String op = (String) this.opMap.get(key);

                if (this.filterMap.get(key) == null) {
                    continue;
                }

                strXml = strXml + key + op +
                    this.filterMap.get(key).toString() + "\r\n";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return strXml;
    }

    /**
     * 添加一条过滤条件
     * @param field 需要添加的字段
     * @param operate 基于枚举对象的操作符
     * @param value 字段
     * @return 当前对象的引用
     */
    public SqlFilter addFilter(String field, OP operate, Object value) {
        if ((value != null) && !"".equals(value) && !"%%".equals(value) &&
                (field != null) && !"".equals(field) && (operate != null)) {
            if (field != null) {
                Pattern p = Pattern.compile("(\\^\\d+)");
                Matcher m = p.matcher(field);

                if (m.find()) {
                    field = m.replaceAll("");
                }
            }

            int count = getSameNameFieldCount(field);

            if (count > 0) {
                field = field + "^" + (count);
            }

            String op = (String) this.enumMap.get(operate);

            if (op.trim().equals("like")) {
                value = "%" + value + "%";
            } else if (op.trim().equals("llike")) {
                value = value + "%";
                op = " like ";
            } else if (op.trim().equals("rlike")) {
                value = "%" + value;
                op = " like ";
            }

            this.filterMap.put(field, value);
            this.opMap.put(field, op);
            this.Fields.add(field);
        }

        return this;
    }

    /**
     * 添加一条过滤条件
     * @param field 需要添加的字段
     * @param operate 元素字符串操作符
     * @param value 字段
     * @return 当前对象的引用
     */
    public SqlFilter addFilter(String field, String op, Object value) {
        if (field != null) {
            Pattern p = Pattern.compile("(\\^\\d+)");
            Matcher m = p.matcher(field);

            if (m.find()) {
                field = m.replaceAll("");
            }
        }

        int count = getSameNameFieldCount(field);

        if (count > 0) {
            field = field + "^" + (count);
        }

        if ((value != null) && !"".equals(value) && !"%%".equals(value) &&
                (field != null) && !"".equals(field)) {
            if (op.trim().equals("like") &&
                    (value.toString().indexOf("%") == -1)) {
                value = "%" + value + "%";
            }

            this.filterMap.put(field, value);
            this.opMap.put(field, " " + op + " ");
            this.Fields.add(field);
        }

        return this;
    }

    /**
     * 把一个已经存在的sqlfilter对象添加到当前对象
     * @param field 需要添加的字段
     * @param operate 操作符
     * @param value 字段
     * @return 当前对象的引用
     */
    public void addFilter(SqlFilter filter, boolean isOr) {
        String op = (isOr) ? " OR " : " AND ";
        this.childMap.put(filter, op);

        /*if (isOr) {
                this.childMap.put(filter, op);
        } else {

                Object[] fields = filter.filterMap.keySet().toArray();

                for (int i = 0; i < fields.length; ++i) {
                        String field = (String) fields[i];
                        String operateion = filter.getOperation(field);
                        Object value = filter.filterMap.get(field);

                        if ((value == null) || ("".equals(value)))
                                continue;

                        addFilter(field, operateion, value);
                }
                if(!filter.attachCondition.equals("")){
                        String spit = filter.attachCondition.toLowerCase().indexOf("and")==-1?" and ":"";
                        this.attachCondition+=spit+filter.attachCondition;
                }

        }*/
    }

    /**
     * 返回当前SqlFilter的sql表达式
     * @return 通过当前对象生成过滤表达式（参数值以?占位符代替）
     */
    public String getFilterExpress() {
        String filterExp = getFilter();

        if ((this.rel.equals("")) && (filterExp.length() > 0)) {
            filterExp = " (" + filterExp + ")";
        }

        return filterExp;
    }

    /**
     * 按照键的顺序返回当前对象中添加的条件值的列表
     * @return 按照键的顺序返回当前对象中添加的条件值的列表
     */
    public List getValueList() {
        List valueList = new ArrayList();
        getValues();
        valueList = getList(this.values, "|");

        return valueList;
    }

    /**
     * 按照键的顺序返回当前对象中添加的条件字段的列表
     * @return 按照键的顺序返回当前对象中添加的条件字段的列表
     */
    public List<String> getFieldList() {
        List fieldList = new ArrayList();
        getFields();
        fieldList = getList(this.fields, "|");

        return fieldList;
    }

    /**
     * 返回当前对象中的过滤条件的个数
     * @return 当前对象中的过滤条件的个数
     */
    public int getFilterSize() {
        return this.filterMap.size();
    }

    /**
     * 返回子过滤条件的个数
     * @return 子过滤条件的个数
     */
    public int getChildSize() {
        return this.childMap.size();
    }

    /**
     * 通过过滤字段名称获取对应的过滤条件值
     * @param field 字段名
     * @return field对应的过滤条件值
     */
    public Object getValue(String field) {
        Object value = null;

        if (this.filterMap.containsKey(field)) {
            value = this.filterMap.get(field);
        }

        return value;
    }

    /**
     * 通过字段名这只过滤条件值
     * @param field 字段名
     * @param value 字段值
     */
    public void setValue(String field, Object value) {
        this.filterMap.put(field, value);
        this.values="";
    }

    public String getOperation(String field) {
        String op = "";

        if (this.opMap.containsKey(field)) {
            op = (String) this.opMap.get(field);
        }

        return op;
    }

    /**
     * 通过字段名这只过滤条件值操作符
     * @param field 字段名
     * @param op    操作符
     */
    public void setOperation(String field, String op) {
        this.opMap.put(field, op);
    }

    /**
     * 移除某个过滤条件
     * @param field 需要移除的字段名
     */
    public void remove(String field) {
        if (filterMap.containsKey(field)) {
            filterMap.remove(field);
            if (opMap.containsKey(field)) {
                opMap.remove(field);
            }
        }
        else if(this.childMap.size()>0){
        	Iterator children = this.childMap.keySet().iterator();
            while (children.hasNext()) {
                SqlFilter child = (SqlFilter) children.next();
                child.remove(field);
            }
        }
        
    }

    /**
     * 移除所有过滤条件
     *
     */
    public void removeAll() {
        filterMap.clear();
        childMap.clear();
        opMap.clear();
        this.values = "";
        this.fields = "";
    }

    public int size() {
        return this.filterMap.size();
    }

    private String getFields() {
        if (this.childMap.size() > 0) {
            Iterator children = this.childMap.keySet().iterator();

            while (children.hasNext()) {
                SqlFilter child = (SqlFilter) children.next();
                String spit = (this.fields.equals("")) ? "" : "|";
                SqlFilter tmp57_56 = this;
                tmp57_56.fields = tmp57_56.fields + spit + child.getFields();
            }
        }

        if (fields.equals("")) {
            getChildExp();
        }

        return this.fields;
    }

    private String getValues() {
        if (this.childMap.size() > 0) {
            Iterator children = this.childMap.keySet().iterator();

            while (children.hasNext()) {
                SqlFilter child = (SqlFilter) children.next();
                String spit = (this.values.equals("")) ? "" : "|";
                SqlFilter tmp57_56 = this;
                tmp57_56.values = tmp57_56.values + spit + child.getValues();
            }
        }

        if ("".equals(values)) {
            getFilterExpress();
        }

        return this.values;
    }

    private List getList(String line, String spit) {
        List list = new ArrayList();
        StringTokenizer lst = new StringTokenizer(line, spit);

        try {
            while (lst.hasMoreElements()) {
                list.add(lst.nextElement());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return list;
    }

    /**
     * 取得本级对象的顾虑条件表达式
     * @return 当前层级的SqlFilter对象的表达式
     */
    private String getFilter() {
        String filterExp = "";
        this.fields = "";
        this.values = "";

        Iterator keys = this.filterMap.keySet().iterator();

        while (keys.hasNext()) {
            String key = (String) keys.next();
            String op = (String) this.opMap.get(key);
            String spit = (filterExp.equals("")) ? "" : this.rel;
            String spit2 = (this.fields.equals("")) ? "" : "|";
            String field = key;

            if (ExtendFields.contains(key)) {
                continue;
            }

            Pattern p = Pattern.compile("(\\^\\d+)");
            Matcher m = p.matcher(field);

            if (m.find()) {
                field = m.replaceAll("");
            }

            filterExp = filterExp + " " + spit + " " + field + op + "? ";

             
            this.fields = this.fields + spit2 + key;
            
            if (this.filterMap.get(key) == null) {
                continue;
            }

            
           
            this.values = this.values + spit2 + this.filterMap.get(key).toString();
        }

        if (this.childMap.size() > 0) {
            if ((filterExp != null) && !"".equals(filterExp)) {
                filterExp = "( " + filterExp + " )";
            }

            filterExp = filterExp + getChildExp();
        }

        this.attachCondition = this.attachCondition.trim();

        if (!(this.attachCondition.equals(""))) {
            if ("".equals(filterExp)) {
                if (this.attachCondition.trim().toLowerCase().startsWith("and")) {
                    this.attachCondition = this.attachCondition.substring(3,
                            this.attachCondition.length());
                }
            } else if (!(this.attachCondition.trim().toLowerCase()
                                                 .startsWith("and"))) {
                this.attachCondition = " and " + this.attachCondition;
            }

            filterExp = filterExp + this.attachCondition;
        }

        return filterExp;
    }

    /**
     * 取得子过滤条件对象的条件表达式
     * @return  子过滤条件对象的条件表达式
     */
    private String getChildExp() {
        String filterExp = "";
        Iterator children = this.childMap.keySet().iterator();
        int index = 0;

        while (children.hasNext()) {
            SqlFilter child = (SqlFilter) children.next();

            if ((child.size() == 0) && (child.childMap.size() == 0) &&
                    "".equals(child.attachCondition.trim())) {
                continue;
            }

            String op = (String) this.childMap.get(child);
            String spit = (filterExp.equals("")) ? "" : op;

            //filterExp = filterExp + spit + "(" + child.getFilter() + ")";
            String subFilter = child.getFilter();

            if ((subFilter != null) && !"".equals(subFilter)) {
                if ((this.size() > this.ExtendFields.size()) ||
                        ((childMap.size() > 1) && (index > 0))) {
                    filterExp = filterExp + op + "(" + subFilter + ")";
                } else {
                    filterExp = filterExp + "(" + subFilter + ")";
                }

                //filterExp = filterExp + op + "(" + subFilter+ ")";
            }

            index++;
        }

        return filterExp;
    }

    /**
     * 获取对象中同名字段的个数（用于添加类似于create_time>= and create_time<= ）
     * @param field 需要检查的字段名称
     * @return 返回同名字段的个数
     */
    private int getSameNameFieldCount(String field) {
        int count = 0;

        try {
            Object[] fieldArr = this.filterMap.keySet().toArray();

            for (int i = 0; i < fieldArr.length; i++) {
                String f = fieldArr[i].toString();

                Pattern p = Pattern.compile(field + "(\\^\\d+)?");
                Matcher m = p.matcher(f);

                if (m.find()) {
                    count++;
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return count;
    }

    /**
     * 判断对象中是否包含某个字段
     * @param field 需要检查的字段
     * @return true、false
     */
    public boolean containsField(String field) {
        if (this.filterMap.containsKey(field)) {
            return true;
        }

        if (this.childMap.size() > 0) {
            Iterator children = this.childMap.keySet().iterator();

            while (children.hasNext()) {
                SqlFilter child = (SqlFilter) children.next();

                if (child.containsField(field)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 把当前SqlFilter对象序列化成字符串用于传输
     * @return 当前对象序列化后的一个utf8编码的字符串
     */
    public String serializable() {
        ByteArrayOutputStream byteArrayOutputStream = null;
        ObjectOutputStream objectOutputStream = null;
        String serStr = "";

        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);

            if (ConfigReader.GetProptery("encoding").equals("true")) {
                serStr = byteArrayOutputStream.toString("ISO-8859-1");
                serStr = java.net.URLEncoder.encode(serStr, "UTF-8");
            } else {
                serStr = byteArrayOutputStream.toString();
                serStr = java.net.URLEncoder.encode(serStr);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        try {
            objectOutputStream.close();
            byteArrayOutputStream.close();
        } catch (Exception e) {
        }

        return serStr;
    }

    /**
     * 得到当前对象的一个克隆（包括子条件对象）
     */
    public SqlFilter clone() {
        SqlFilter ft = new SqlFilter();
        ft.filterMap = (HashMap) this.filterMap.clone();
        ft.opMap = (HashMap) this.opMap.clone();
        ft.childMap = (HashMap) this.childMap.clone();
        ft.attachCondition = this.attachCondition;
        ft.getFilterExpress();
        return ft;
    }

    /**
     *
     * @param filter 带有查询条件的SqlFilter对象
     * @param prifix 标识扩展字段的前缀
     * @param propertyNameField 扩展属性表的属性名字段
     * @param propertyValueField  扩展属性表的属性值字段
     * @return 返回一组扩展属性组成的join语句
     */
    public static String GenerateJoinByFilter(SqlFilter filter,
        String tableName, String prifix, String localKey,
        String associationKey, String propertyNameField,
        String propertyValueField) {
        String strJoin = "";
        ArrayList<String> fields = filter.Fields;

        if (fields != null) {
            int cutIndex = 0;

            for (int i = 0; i < fields.size(); i++) {
                String field = fields.get(i);

                if (field.startsWith(prifix)) {
                    String alias = " alias_" + cutIndex;
                    String propertyName = field.replace(prifix, "");
                    String associationjoin = localKey + "=" + alias + "." +
                        associationKey + " AND ";
                    String strItem = " Inner Join  " + tableName + alias +
                        " ON " + associationjoin + alias + "." +
                        propertyNameField + " = '" + propertyName + "' AND " +
                        alias + "." + propertyValueField + " like  '%" +
                        filter.getValue(field) + "%'";
                    strJoin += (strItem + "\r\n");
                    //filter.remove(field);
                    filter.ExtendFields.add(field);
                    cutIndex++;
                }
            }
        }

        return strJoin;
    }

    /**
     * 把一个字符串反序列化成一个SqlFilter对象
     * @param serializable
     * @return 一个通过serializable反序列化生成的SqlFilter对象
     */
    public static SqlFilter Derializable(String serializable) {
        SqlFilter ft = null;
        ByteArrayInputStream byteArrayInputStream = null;
        ObjectInputStream objectInputStream = null;
        String redStr = "";

        try {
            if (ConfigReader.GetProptery("encoding").equals("true")) {
                redStr = java.net.URLDecoder.decode(serializable, "UTF-8");
                byteArrayInputStream = new ByteArrayInputStream(redStr.getBytes(
                            "ISO-8859-1"));
            }
            else {
                redStr = java.net.URLDecoder.decode(serializable);
                byteArrayInputStream = new ByteArrayInputStream(redStr.getBytes());
            }

            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            ft = (SqlFilter) objectInputStream.readObject();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        try {
            objectInputStream.close();
            byteArrayInputStream.close();
        } catch (Exception e) {
        }

        return ft;
    }
    
    /**
     * 操作符枚举
     * @author Administrator
     *
     */
    public static enum OP {EQUALS,
        NOT_EQUALS,
        LIKE,
        NOT_LIKE,
        LESSTHEN,
        LESSTHEN_OR_EQUALS,
        MORETHEN,
        MORETHEN_OR_EQUALS,
        LEFT_LIKE,
        RIGHT_LIKE,
        IN,
        NOT_IN;
    }
    
    
}
